package cn.supermaster.management.schedule.quartz;

import cn.supermaster.management.common.utils.CheckUtils;
import cn.supermaster.management.common.utils.TextUtils;
import cn.supermaster.management.common.utils.spring.SpringUtils;
import cn.supermaster.management.schedule.domain.ScheduleTask;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;

/**
 * All rights Reserved, Designed By www.super-bytecode.com
 *
 * @ProjectName: supermaster-management
 * @Package: cn.supermaster.management.task.util
 * @ClassName: ScheduleTaskInvokeUtil
 * @Description: [任务执行工具]
 * <p> </p>
 * @Author: [Lance Ting]
 * @Date: 2021/1/13 10:00
 * @Version: V1.0
 * @Copyright: 2021 www.super-bytecode.com Inc. All rights reserved.
 * TODO: 注意,本文件Lance Ting所作,如果转载或使用请标明具体出处!
 **/
public class ScheduleTaskInvokeUtil {

    /**
     * @description: [执行方法]
     * <p></P>
     * @title: invokeMethod
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: sysJob 系统任务
     * @return: void
     * Throws: java.lang.Exception
     */
    public static void invokeMethod(ScheduleTask scheduleTask) throws Exception {
        String invokeTarget = scheduleTask.getInvokeTarget();
        String beanName = getBeanName(invokeTarget);
        String methodName = getMethodName(invokeTarget);
        List<Object[]> methodParams = getMethodParams(invokeTarget);

        if (!isValidClassName(beanName)) {
            Object bean = SpringUtils.getBean(beanName);
            invokeMethod(bean, methodName, methodParams);
        } else {
            Object bean = Class.forName(beanName).newInstance();
            invokeMethod(bean, methodName, methodParams);
        }
    }

    /**
     * @description: [调用任务方法]
     * <p></P>
     * @title: invokeMethod
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: bean 目标对象
     * @Param: methodName 方法名称
     * @Param: methodParams 方法参数
     * @return: void
     * @Throws: java.lang.NoSuchMethodException
     * @Throws: java.lang.SecurityException
     * @Throws: java.lang.IllegalAccessException
     * @Throws: java.lang.IllegalArgumentException
     */
    private static void invokeMethod(Object bean, String methodName, List<Object[]> methodParams)
            throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException {
        if (CheckUtils.isNotNull(methodParams) && methodParams.size() > 0) {
            Method method = bean.getClass().getDeclaredMethod(methodName, getMethodParamsType(methodParams));
            method.invoke(bean, getMethodParamsValue(methodParams));
        } else {
            Method method = bean.getClass().getDeclaredMethod(methodName);
            method.invoke(bean);
        }
    }

    /**
     * @description: [校验是否为为class包名]
     * <p></P>
     * @title: isValidClassName
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: invokeTarget  名称
     * @return: boolean true是 false否
     */
    public static boolean isValidClassName(String invokeTarget) {
        return TextUtils.countMatches(invokeTarget, ".") > 1;
    }

    /**
     * @description: [获取bean名称]
     * <p></P>
     * @title: getBeanName
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: invokeTarget 目标字符串
     * @return: java.lang.String bean名称
     */
    public static String getBeanName(String invokeTarget) {
        String beanName = TextUtils.substringBefore(invokeTarget, "(");
        return TextUtils.substringBeforeLast(beanName, ".");
    }

    /**
     * @description: [获取bean方法]
     * <p></P>
     * @title: getMethodName
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: invokeTarget 目标字符串
     * @return: java.lang.String method方法
     */
    public static String getMethodName(String invokeTarget) {
        String methodName = TextUtils.substringBefore(invokeTarget, "(");
        return TextUtils.substringAfterLast(methodName, ".");
    }

    /**
     * @description: [获取Method方法参数相关列表]
     * <p></P>
     * @title: getMethodParams
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: invokeTarget  目标字符串
     * @return: java.util.List<java.lang.Object [ ]> method方法相关参数列表
     */
    public static List<Object[]> getMethodParams(String invokeTarget) {
        // 获取方法信息
        String targetMethod = TextUtils.substringBetween(invokeTarget, "(", ")");
        if (TextUtils.isEmpty(targetMethod)) {
            return null;
        }
        //
        String[] params = targetMethod.split(",");
        List<Object[]> classs = new LinkedList<>();
        //
        for (int idx = 0; idx < params.length; idx++) {
            String param = TextUtils.trimToEmpty(params[idx]);
            String param_ = null;
            // String字符串类型，包含'
            if (TextUtils.contains(param, "'")) {
                param_ = TextUtils.replace(param, "'", "");
                classs.add(new Object[]{param_, String.class});
            }
            // boolean布尔类型，等于true或者false
            else if (CheckUtils.isBoolean(param)) {
                classs.add(new Object[]{Boolean.valueOf(param), Boolean.class});
            }
            // long长整形，包含L
            else if (TextUtils.containsIgnoreCase(param, "L")) {
                param_ = TextUtils.replaceIgnoreCase(param, "L", "");
                classs.add(new Object[]{Long.valueOf(param_), Long.class});
            }
            // double浮点类型，包含D
            else if (TextUtils.containsIgnoreCase(param, "D")) {
                param_ = TextUtils.replaceIgnoreCase(param, "D", "");
                classs.add(new Object[]{Double.valueOf(param_), Double.class});
            }
            // 其他类型归类为整形
            else {
                classs.add(new Object[]{Integer.valueOf(param), Integer.class});
            }
        }
        return classs;
    }

    /**
     * @description: [获取参数类型]
     * <p></P>
     * @title: getMethodParamsType
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: methodParams 参数相关列表
     * @return: java.lang.Class<?>[] 参数类型列表
     */
    public static Class<?>[] getMethodParamsType(List<Object[]> methodParams) {
        Class<?>[] classs = new Class<?>[methodParams.size()];
        int index = 0;
        for (Object[] param : methodParams) {
            classs[index] = (Class<?>) param[1];
            index++;
        }
        return classs;
    }

    /**
     * @description: [获取参数值]
     * <p></P>
     * @title: getMethodParamsValue
     * @author: Lance Ting
     * @date: 2021-01-13
     * @param: methodParams  参数相关列表
     * @return: java.lang.Object[] 参数值列表
     * @throws:
     */
    public static Object[] getMethodParamsValue(List<Object[]> methodParams) {
        Object[] classs = new Object[methodParams.size()];
        int index = 0;
        for (Object[] param : methodParams) {
            classs[index] = (Object) param[0];
            index++;
        }
        return classs;
    }
}
